﻿using Newtonsoft.Json;
using Sustainalytics.Auth.Claims;
using Sustainalytics.Entities;
using Sustainalytics.ScreeningTool.BL;
using Sustainalytics.ScreeningTool.BL.Exceptions;
using Sustainalytics.ScreeningTool.BL.Model;
using Sustainalytics.ScreeningTool.Service.Utility;
using Sustainalytics.Utils;
using Sustainalytics.Utils.Serilog;
using Sustainalytics.Utils.WebApi.ErrorCodes;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.ScreeningTool.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/criteria")]
    public class CriteriaController : ApiController, ICriteriaController
    {
        private readonly ICompanyScreening _companyScreening;

        public CriteriaController(
            ICompanyScreening companyScreening)
        {
            try
            {
                _companyScreening = companyScreening;
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            }
        }

        [Route("{criteriaId}")]
        public HttpResponseMessage Get([FromUri] Guid criteriaId, [FromUri] CriteriaOptions options)
        {
            HttpResponseMessage response;
            var dto = (object)null;
            var dtos = new List<CriteriaTypeFour>();
            try
            {
                switch (options.CriteriaType)
                {
                    case CriteriaTypeEnum.CriteriaType1:
                        {
                            var univ = new List<int>();
                            var c = _companyScreening.LoadTemplateCriteria<CriteriaTypeOne>(criteriaId);
                            if (c != null)
                            {
                                var cl2 = _companyScreening.GetCriteriaLevelTwoByLevel3Id(c.CriteriaLevel3Id);
                                if (cl2 != null)
                                {
                                    univ = ClaimsPrincipal.Current.Claims.GetUniverseIds(cl2.UniverseFeature);
                                }
                            }
                            var cd = _companyScreening.LoadCriteriaTypeOneData(criteriaId, univ);
                            dto = CriteriaTypeOne.CriteriaTypeOneWithGraph(c, cd);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType2:
                        {
                            dto = _companyScreening.GetTemplateCriteriaById(criteriaId);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType3:
                        {
                            var univ = new List<int>();
                            var totalCount = 0;
                            var c = _companyScreening.GetTemplateCriteriaById(criteriaId);
                            if (c != null)
                            {
                                var cl2 = _companyScreening.GetCriteriaLevelTwoByLevel3Id(c.CriteriaLevel3Id);
                                if (cl2 != null)
                                {
                                    univ = ClaimsPrincipal.Current.Claims.GetUniverseIds(cl2.UniverseFeature);
                                }
                            }
                            var cd = _companyScreening.LoadCriteriaTypeThreeData(criteriaId, univ, options.Skip, options.Take, options.SearchText ?? string.Empty, out totalCount);
                            dto = CriteriaTypeThree.CriteriaTypeThreeWithGraph(c, cd, totalCount);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType4:
                        {
                            dtos = _companyScreening.LoadCriteriaTypeFour(criteriaId);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType5:
                        {
                            dto = _companyScreening.LoadTemplateCriteriaTypeFive(criteriaId);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType25:
                        {
                            dto = _companyScreening.LoadTemplateCriteriaType25(criteriaId);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType6:
                        {
                            var univ = new List<int>();
                            var c = _companyScreening.LoadTemplateCriteria<CriteriaTypeSix>(criteriaId);
                            if (c != null)
                            {
                                var cl2 = _companyScreening.GetCriteriaLevelTwoByLevel3Id(c.CriteriaLevel3Id);
                                if (cl2 != null)
                                {
                                    univ = ClaimsPrincipal.Current.Claims.GetUniverseIds(cl2.UniverseFeature);
                                }
                            }
                            var cd = _companyScreening.LoadCriteriaTypeSixData(criteriaId, univ);
                            dto = CriteriaTypeSix.CriteriaTypeSixWithGraph(c, cd);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType7:
                        {
                            var univ = new List<int>();
                            var totalCount = 0;
                            var c = _companyScreening.GetTemplateCriteriaById(criteriaId);
                            if (c != null)
                            {
                                var cl2 = _companyScreening.GetCriteriaLevelTwoByLevel3Id(c.CriteriaLevel3Id);
                                if (cl2 != null)
                                {
                                    univ = ClaimsPrincipal.Current.Claims.GetUniverseIds(cl2.UniverseFeature);
                                }
                            }
                            var cd = _companyScreening.LoadCriteriaTypeSevenData(criteriaId, univ, options.Skip, options.Take, "", out totalCount);
                            dto = CriteriaTypeSeven.CriteriaTypeSevenWithGraph(c, cd, totalCount);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType8:
                        {
                            dto = _companyScreening.LoadTemplateCriteria<CriteriaTypeEight>(criteriaId);
                        }
                        break;

                    case CriteriaTypeEnum.CriteriaType16:
                        {
                            var univ = new List<int>();
                            var c = _companyScreening.LoadCriteriaType16(criteriaId);
                            if (c != null)
                            {
                                var cl2 = _companyScreening.GetCriteriaLevelTwoByLevel3Id(c.CriteriaLevel3Id);
                                if (cl2 != null)
                                {
                                    univ = ClaimsPrincipal.Current.Claims.GetUniverseIds(cl2.UniverseFeature);
                                }
                            }
                            var cd = _companyScreening.LoadCriteriaType16Data(criteriaId, univ);
                            dto = CriteriaType16.CriteriaType16WithGraph(c, cd);
                        }
                        break;
                }

                if (options.CriteriaType == CriteriaTypeEnum.CriteriaType4)
                    response = dtos == null ? Request.CreateResponse(HttpStatusCode.NotFound, new { criteriaId, options }) : Request.CreateResponse(HttpStatusCode.OK, dtos);
                else
                    response = dto == null ? Request.CreateResponse(HttpStatusCode.NotFound, new { criteriaId, options }) : Request.CreateResponse(HttpStatusCode.OK, dto);
            }
            catch (ArgumentException ex)
            {
                response = Request.CreateResponse(HttpStatusCode.NotFound, ex.Message);
            }
            catch (AuthorizationException)
            {
                response = Request.CreateResponse(HttpStatusCode.Unauthorized,
                                   new { ErrorStatusCode = WebAPIGeneralErrorCodes.AuthorizationFailed, Details = dto });
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
            
            return response;
        }

        [Route("")]
        public HttpResponseMessage Post([FromUri] Guid criteriaLevel2Id, [FromBody] object checks)
        {
            HttpResponseMessage response;
            var listChecks = JsonConvert.DeserializeObject<List<string>>(checks.ToString());
            var finalList = new List<TemplateCheck>();
            try
            {
                foreach (var item in listChecks)
                {
                    var newItem = JsonConvert.DeserializeObject<TemplateCheck>(item);
                    finalList.Add(newItem);
                }
                var listTempCriteria = _companyScreening.GetDataPointsByCriteriaLevel2IdAndChecks(criteriaLevel2Id, finalList);
                return Request.CreateResponse(HttpStatusCode.OK, listTempCriteria);
            }
            catch (Exception ex)
            {
                response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
            
            return response;
        }
    }
}
